home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / xlib / xlib06p2 / xrect.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  12.0 KB  |  442 lines

  1. #include "xinternl.h"
  2. #include <conio.h>
  3. #include <mem.h>
  4.  
  5. #include "xdefs.h"
  6.  
  7. /*==================================================================
  8. XRECT.CPP contains the basic functions for rectangle fills and
  9. copies in mode X.
  10.  
  11. These routines were written initially by Themie Gouthas and
  12. company and modified March 1995 by Victor B. Putz.
  13. ===================================================================*/
  14.  
  15.  
  16. extern unsigned char * pbVGABuffer;
  17. extern int ScrnLogicalByteWidth;
  18.  
  19. unsigned char abLeftClipPlaneMask[] = {
  20.   0x0f,
  21.   0x0e,
  22.   0x0c,
  23.   0x08
  24. };
  25.  
  26. unsigned char abRightClipPlaneMask[] = {
  27.   0x0f,
  28.     0x01,
  29.     0x03,
  30.     0x07
  31. };
  32.  
  33. /*
  34. _OrderRectPoints() swaps two coordinates if necessary so that one is the top left
  35. and the other is the bottom right
  36. */
  37. inline void _SwapPoints(
  38.     xScreenCoord_t * piLeft,
  39.   xScreenCoord_t * piTop,
  40.   xScreenCoord_t * piRight,
  41.   xScreenCoord_t * piBottom
  42. )
  43. {
  44.     xScreenCoord_t iTemp;
  45.   if ( *piLeft > *piRight ) {
  46.     iTemp = *piLeft;
  47.     *piLeft = *piRight;
  48.     *piRight = iTemp;
  49.   }
  50.   if ( *piTop > *piBottom ) {
  51.     iTemp = *piTop;
  52.     *piTop = *piBottom;
  53.     *piBottom = iTemp;
  54.   }
  55. }
  56.  
  57.  
  58. extern void _HorizontalLine(
  59.     xPageHandle_t wOffset,
  60.     xScreenCoord_t iLeftX,
  61.     xScreenCoord_t iY,
  62.     int iLength,
  63.     xColor_t iColor
  64. );
  65.  
  66.  
  67. void  x_rect_fill(         /* draw a single colour filled rectangle */
  68.   xScreenCoord_t wStartX,
  69.   xScreenCoord_t wStartY,
  70.   xScreenCoord_t wEndX,
  71.   xScreenCoord_t wEndY,
  72.   xPageHandle_t wPageBase,
  73.   xColor_t wColor
  74. )
  75. {
  76.     _SwapPoints( &wStartX, &wStartY, &wEndX, &wEndY );
  77.   BYTE * pbBase;
  78.   BYTE * pb;
  79.   int iPortTemp;
  80.   int i;
  81.  
  82.   int iXSize = ( wEndX - wStartX ) + 1;
  83.     int iYSize = ( wEndY - wStartY ) + 1;
  84.   //trivial case -- just draw a line
  85.   if ( iYSize == 1 ) {
  86.     _HorizontalLine( wPageBase, wStartX, wStartY, iXSize, wColor );
  87.   }
  88.  
  89.   //set up our pointer to the top left of the rectangle
  90.   pbBase = pbVGABuffer + wPageBase + ( ScrnLogicalByteWidth * wStartY ) + wStartX / 4;
  91.  
  92.   //Start on the left
  93.   if ( iPortTemp = ( wStartX & 3 ) ) {
  94.     outp( SC_INDEX, 0x02 );
  95.     outp( SC_INDEX + 1, abLeftClipPlaneMask[ iPortTemp ] );
  96.     pb = pbBase;
  97.     i = iYSize;
  98.     while ( i-- ) {
  99.       *pb = ( BYTE )wColor;
  100.       pb += ScrnLogicalByteWidth;
  101.     }
  102.     iXSize -= ( 4 - iPortTemp );
  103.     pbBase++;
  104.   }
  105.   //now do the middle chunk
  106.   if ( iPortTemp = ( iXSize / 4 ) ) {
  107.     outpw( SC_INDEX, 0x0f02 );
  108.     iXSize &= 3;
  109.     pb = pbBase;
  110.     i = iYSize;
  111.     while ( i-- ) {
  112.       memset( pb, wColor, iPortTemp );
  113.       pb += ScrnLogicalByteWidth;
  114.     }
  115.     pbBase += iPortTemp;
  116.   }
  117.   //...and finally clean up the right edge
  118.   if ( iXSize ) {
  119.     outp( SC_INDEX, 0x02 );
  120.     outp( SC_INDEX + 1, abRightClipPlaneMask[ iXSize ] );
  121.     while ( iYSize-- ) {
  122.       *pbBase = ( BYTE )wColor;
  123.       pbBase += ScrnLogicalByteWidth;
  124.     }
  125.   }
  126. }
  127.  
  128. extern xScreenCoord_t TopClip;                /* Clipping rectangle                  */
  129. extern xScreenCoord_t BottomClip;
  130. extern xScreenCoord_t LeftClip;
  131. extern xScreenCoord_t RightClip;
  132.  
  133.  
  134. void  x_rect_fill_clipped(   /* draw a single colour filled */
  135.   xScreenCoord_t StartX,        /* and clipped rectangle       */
  136.   xScreenCoord_t StartY,
  137.   xScreenCoord_t EndX,
  138.   xScreenCoord_t EndY,
  139.   xPageHandle_t PageBase,
  140.   xColor_t color
  141. )
  142. {
  143.     _SwapPoints( &StartX, &StartY, &EndX, &EndY );
  144.     if ( StartX > RightClip ) {
  145.     return;
  146.   }
  147.     if ( StartX < LeftClip ) {
  148.     StartX = LeftClip;
  149.   }
  150.   if ( EndX < LeftClip ) {
  151.     return;
  152.   }
  153.   if ( EndX > RightClip ) {
  154.     EndX = RightClip;
  155.   }
  156.     if ( StartY > BottomClip ) {
  157.     return;
  158.   }
  159.     if ( StartY < TopClip ) {
  160.     StartY = TopClip;
  161.   }
  162.   if ( EndY < TopClip ) {
  163.     return;
  164.   }
  165.   if ( EndY > BottomClip ) {
  166.     EndY = BottomClip;
  167.   }
  168.  
  169.   x_rect_fill( StartX, StartY, EndX, EndY, PageBase, color );
  170.  
  171. }
  172.  
  173. void  x_cp_vid_rect(       /* Copy rect region within VRAM          */
  174.   xScreenCoord_t SourceStartX,
  175.   xScreenCoord_t SourceStartY,
  176.   xScreenCoord_t SourceEndX,
  177.   xScreenCoord_t SourceEndY,
  178.   xScreenCoord_t DestStartX,
  179.   xScreenCoord_t DestStartY,
  180.   xPageHandle_t SourcePageBase,
  181.   xPageHandle_t DestPageBase,
  182.   int SourceBitmapWidth,
  183.   int DestBitmapWidth
  184. )
  185. {
  186.     _SwapPoints( &SourceStartX, &SourceStartY, &SourceEndX, &SourceEndY );
  187.     //select bit mask to take all latches from the latches and none
  188.   //from the CPU so we can write the latch contents directly to memory
  189.   outpw( GC_INDEX, 0x0 + BIT_MASK );
  190.   BYTE * pbSource = pbVGABuffer + ( SourceBitmapWidth / 4 ) * SourceStartY + ( SourceStartX / 4 ) + SourcePageBase;
  191.     BYTE * pbDest = pbVGABuffer + ( DestBitmapWidth / 4 ) * DestStartY + ( DestStartX / 4 ) + DestPageBase;
  192.   BYTE bLeftPlaneMask = abLeftClipPlaneMask[ SourceStartX & 3 ];
  193.   BYTE bRightPlaneMask = abRightClipPlaneMask[ SourceEndX & 3 ];
  194.   //now get the number of bytes to copy
  195.   if ( SourceStartX > SourceEndX ) {
  196.     return;
  197.   }
  198.   //this is really the bytes to copy minus one, since we know there must
  199.   //be at least one byte ( if there isn't we just return )
  200.   int iBytesToCopy = ( ( SourceEndX - 1 ) - ( SourceStartX & ( ~0x03 ) ) / 4 );
  201.   if ( iBytesToCopy == 0 ) {
  202.     bLeftPlaneMask &= bRightPlaneMask;
  203.   }
  204.   int iHeightToCopy = SourceEndY - SourceStartY;
  205.   int iDestSkip = DestBitmapWidth / 4 - iBytesToCopy - 1;
  206.   int iSourceSkip = SourceBitmapWidth / 4 - iBytesToCopy - 1;
  207.   while ( iHeightToCopy-- ) {
  208.       int i = iBytesToCopy;
  209.     //do left edge
  210.     outp( SC_INDEX + 1, bLeftPlaneMask );
  211.     *pbDest++ = *pbSource++;    //copied through latches...
  212.     --i;
  213.     //now since iBytesToCopy is the number of bytes to copy minus one,
  214.     //if there was only the one byte we're now negative and if it's
  215.     //zero we're ready for the right edge.  If it's more than zero, we've
  216.     //got the middle to do
  217.     if ( i > 0 ) {
  218.       //do the middle part
  219.       outp( SC_INDEX + 1, 0x0f );
  220.       while( i > 0 ) {
  221.         *pbDest++ = *pbSource++;
  222.         --i;
  223.       }
  224.     }
  225.     //now check for the right edge;
  226.     if ( i == 0 ) {
  227.       outp( SC_INDEX + 1, bRightPlaneMask );
  228.       *pbDest++ = *pbSource++;
  229.     }
  230.     pbDest += iDestSkip;
  231.     pbSource += iSourceSkip;
  232.   }
  233.   //now restore the controller so that it reads all from the cpu and
  234.   //not from the latches.
  235.   outp( GC_INDEX + 1, 0xff );
  236. }
  237.  
  238. /* Copy a rectangular region of a VGA screen, with x coordinates
  239.  rounded to the nearest byte -- source and destination may overlap.
  240.  SrcRight is rounded up, and the left edges are rounded down, to ensure
  241.  that the pixels pointed to by the arguments are inside the rectangle.
  242.  
  243.  The width of the rectangle in bytes (width in pixels / 4)
  244.  cannot exceed 255.
  245.  
  246.  By Matthew McKenzie, converted from assembler by V. Putz
  247.  
  248.  Note-- This seems to be a simplified version of x_cp_vid_rect with
  249.  no left or right clipping ( just uses nibble boundaries ).  It also
  250.  includes a bit of sensing to determine where to start and how to
  251.  increment counters.  Beyond that the functions are essentially the same.
  252. */
  253.  
  254. void x_shift_rect (
  255.     xScreenCoord_t SrcLeft,
  256.     xScreenCoord_t SrcTop,
  257.   xScreenCoord_t SrcRight,
  258.     xScreenCoord_t SrcBottom,
  259.   xScreenCoord_t DestLeft,
  260.     xScreenCoord_t DestTop,
  261.     xPageHandle_t ScreenOffs
  262. )
  263. {
  264.     _SwapPoints( &SrcLeft, &SrcTop, &SrcRight, &SrcBottom );
  265.     //first get new "rounded" coordinates:
  266.   int iSourceLeft = SrcLeft / 4;
  267.   int iDestLeft = DestLeft / 4;
  268.   int iSourceRight = ( SrcRight + 3 ) / 4;
  269.   //now find out what copy type we're doing.
  270.   enum copyType_t {
  271.     fromTopLeft,
  272.     fromBottomRight
  273.   };
  274.   copyType_t copyType = fromTopLeft;
  275.   if ( DestTop == SrcTop ) {
  276.     if ( SrcLeft == DestLeft ) {
  277.       return;
  278.     }
  279.     if ( DestLeft < SrcLeft ) {
  280.       copyType = fromTopLeft;
  281.     }
  282.     else {
  283.       copyType = fromBottomRight;
  284.     }
  285.   }
  286.   else if ( DestTop < SrcTop ) {
  287.     copyType = fromTopLeft;
  288.   }
  289.   else {
  290.     copyType = fromBottomRight;
  291.   }
  292.   //now find the skip and starting points
  293.   int iWidthSkip = 0;
  294.   int iXMotion = 0;
  295.   BYTE * pbDest = NULL;
  296.   BYTE * pbSource = NULL;
  297.   int iBytesToCopy = iSourceRight - iSourceLeft;
  298.   int iHeightToCopy = SrcBottom - SrcTop;
  299.   switch ( copyType ) {
  300.     case fromTopLeft:
  301.         pbDest = pbVGABuffer + ScreenOffs + ( DestTop * ScrnLogicalByteWidth ) + iDestLeft;
  302.       pbSource = pbVGABuffer + ScreenOffs + ( SrcTop * ScrnLogicalByteWidth ) + iSourceLeft;
  303.       iWidthSkip = ScrnLogicalByteWidth - iBytesToCopy;
  304.       iXMotion = 1;
  305.     break;
  306.     case fromBottomRight:
  307.         pbDest = pbVGABuffer + ScreenOffs + ( ( DestTop + iHeightToCopy ) * ScrnLogicalByteWidth ) + iDestLeft + iBytesToCopy;
  308.       pbSource = pbVGABuffer + ScreenOffs + ( SrcBottom * ScrnLogicalByteWidth ) + iSourceRight;
  309.       iWidthSkip = -( ScrnLogicalByteWidth - iBytesToCopy );
  310.       iXMotion = -1;
  311.     break;
  312.   }
  313.   //okay!  Now we just select the mask to copy all bits through the latches...
  314.   outpw( SC_INDEX, 0x0f02 );
  315.   outpw( GC_INDEX, BIT_MASK );
  316.     //now copy the data!
  317.   while ( iHeightToCopy-- ) {
  318.       int i = iBytesToCopy;
  319.     while( i-- ) {
  320.       *pbDest = *pbSource;
  321.       pbDest += iXMotion;
  322.       pbSource += iXMotion;
  323.     }
  324.     pbDest += iWidthSkip;
  325.     pbSource += iWidthSkip;
  326.   }
  327.   //now restore the controller so that it reads all from the cpu and
  328.   //not from the latches.
  329.   outp( GC_INDEX + 1, 0xff );
  330. }
  331.  
  332.  
  333. /*
  334. @func Fills a rectangular region with a given pattern.  DOES NOT FUNCTION
  335. PROPERLY!
  336. */
  337. void x_rect_pattern(
  338.   xScreenCoord_t StartX,
  339.   xScreenCoord_t StartY,
  340.   xScreenCoord_t EndX,
  341.   xScreenCoord_t EndY,
  342.   xPageHandle_t PageBase,
  343.   BYTE * Pattern
  344. )
  345. {
  346.     _SwapPoints( &StartX, &StartY, &EndX, &EndY );
  347.     BYTE * pbDisplayPattern = pbVGABuffer + PATTERN_BUFFER;
  348.   BYTE * pbDest = pbVGABuffer + PageBase + StartX / 4 + ( ScrnLogicalByteWidth * StartY );
  349.  
  350.   //download the pattern to screen memory
  351.   BYTE * pbPatternCount = Pattern;
  352.   outp( SC_INDEX, MAP_MASK );
  353.   for ( int i = 4; i != 0; --i ) {
  354.     outp( SC_INDEX + 1, 0x01 );
  355.     *pbDisplayPattern = *pbPatternCount++;
  356.     outp( SC_INDEX + 1, 0x02 );
  357.     *pbDisplayPattern = *pbPatternCount++;
  358.     outp( SC_INDEX + 1, 0x04 );
  359.     *pbDisplayPattern = *pbPatternCount++;
  360.     outp( SC_INDEX + 1, 0x08 );
  361.     *pbDisplayPattern = *pbPatternCount++;
  362.     ++pbDisplayPattern;
  363.   }
  364.   //select all bit transfer contents from the latches, not CPU
  365.   outpw( GC_INDEX, BIT_MASK );
  366.   int iTemp = *pbDisplayPattern;
  367.   int iPortTemp = 0;
  368.   x_rect_fill( StartX, StartY, EndX, EndY, PageBase, iTemp );
  369.   return;
  370. /*
  371.   outp( GC_INDEX + 1, 0xff );
  372.  
  373.  
  374.   int iXSize = ( EndX - StartX ) + 1;
  375.     int iYSize = ( EndY - StartY ) + 1;
  376.  
  377.   for ( i = iYSize; i != 0; --i ) {
  378.       BYTE * pb = pbDest + ( ScrnLogicalByteWidth * ( iYSize - i - 1 ) );
  379.       iTemp = pbDisplayPattern[ ( iYSize - i ) & 3 ];
  380.     if ( iPortTemp = ( StartX & 3 ) ) {
  381.       outp( SC_INDEX, 0x02 );
  382.       outp( SC_INDEX + 1, abLeftClipPlaneMask[ iPortTemp ] );
  383.       *pb++ = ( BYTE )iTemp;
  384.       iXSize -= ( 4 - iPortTemp );
  385.       pb++;
  386.     }
  387.     //now do the middle chunk
  388.     if ( iPortTemp = ( iXSize / 4 ) ) {
  389.       outpw( SC_INDEX, 0x0f02 );
  390.       iXSize &= 3;
  391.       memset( pb, iTemp, iPortTemp );
  392.       pb += iPortTemp;
  393.     }
  394.     //...and finally clean up the right edge
  395.     if ( iXSize ) {
  396.       outp( SC_INDEX, 0x02 );
  397.       outp( SC_INDEX + 1, abRightClipPlaneMask[ iXSize ] );
  398.       *pb = ( BYTE )iTemp;
  399.     }
  400.   }
  401. */
  402. }
  403.  
  404. void x_rect_pattern_clipped(  /* draw a pattern filled clipped   */
  405.   xScreenCoord_t StartX,          /* rectangle                       */
  406.   xScreenCoord_t StartY,
  407.   xScreenCoord_t EndX,
  408.   xScreenCoord_t EndY,
  409.   xPageHandle_t PageBase,
  410.   BYTE * Pattern
  411. )
  412. {
  413.     _SwapPoints( &StartX, &StartY, &EndX, &EndY );
  414.     if ( StartX > RightClip ) {
  415.     return;
  416.   }
  417.     if ( StartX < LeftClip ) {
  418.     StartX = LeftClip;
  419.   }
  420.   if ( EndX < LeftClip ) {
  421.     return;
  422.   }
  423.   if ( EndX > RightClip ) {
  424.     EndX = RightClip;
  425.   }
  426.     if ( StartY > BottomClip ) {
  427.     return;
  428.   }
  429.     if ( StartY < TopClip ) {
  430.     StartY = TopClip;
  431.   }
  432.   if ( EndY < TopClip ) {
  433.     return;
  434.   }
  435.   if ( EndY > BottomClip ) {
  436.     EndY = BottomClip;
  437.   }
  438.  
  439.   x_rect_pattern( StartX, StartY, EndX, EndY, PageBase, Pattern );
  440.  
  441. }
  442.